#pragma once

#include <iostream>
#include <string>
#include <functional>

std::string getThreadName()
{
    static int number = 1;
    char name[64];
    snprintf(name, sizeof(name), "thread-%d", number++);
    return name;
}

template<class T>
using func_t = std::function<void(T&)>;

template<class T>
class Thread
{
public:
    Thread(const std::string& threadName, func_t<T&> func, T data)
    : _tid(0), _threadName(threadName), _isRunning(false), _func(func), _data(data)
    {}

    static void* threadRoutine(void* args) //若非static，参数会隐含this指针
    {
        Thread* ts = static_cast<Thread*>(args);
        ts->_func(ts->_data);
        return nullptr;
    }

    bool start()
    {
        int n = pthread_create(&_tid, nullptr, threadRoutine, this); //传this指针，使threadRoutine能调到_func()
        if(n == 0) 
        {
            _isRunning = true;
            return true;
        }
        return false;
    }

    bool join()
    {
        if(_isRunning == false) return false;
        int n = pthread_join(_tid, nullptr);
        if(n == 0) 
        {
            _isRunning = false;
            return true;
        }
        return false;
    }

    bool isRunning()
    {
        return _isRunning;
    }

    std::string getThreadName()
    {
        return _threadName;
    }

    ~Thread()
    {}
private:
    pthread_t _tid;
    std::string _threadName;
    bool _isRunning;
    func_t<T> _func;
    T _data;
};